//
//  NetWorkBaseAPIManager.m
//  TuanLife
//
//  Created by 伏圣文 on 2017/12/23.
//  Copyright © 2017年 HuiNaMac. All rights reserved.
//

#import "NetWorkBaseAPIManager.h"
#import "FSWJSONResponseSerializerWithData.h"
#import <AFNetworking/AFNetworking.h>
#import <JSONKit/JSONKit.h>
#import "MainNavigationVC.h"
#import "LoginController.h"

#import "MainNavigationVC.h"
#import "BaseViewController.h"
#define kNetworkMethodName @[@"Get", @"Post", @"Put", @"Delete",@"Patch"]

@implementation NetWorkBaseAPIManager

+ (NetWorkBaseAPIManager *)manager{
    static NetWorkBaseAPIManager *_instance = nil;
    static dispatch_once_t pred;
    dispatch_once(&pred, ^{
        _instance = [[self alloc] init];
    });
    return _instance;
}

- (void)requestHttpWithMethod:(NetworkMethod)methodName url:(NSString *)url parameters:(NSDictionary *)params isJson:(BOOL)isJson success:(void (^)(id))success failure:(void (^)(NSString *))failure{
    
    AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
    session.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html",@"text/json",@"text/javascript",@"text/plain",@"text/xml", nil];
    //    session.responseSerializer = [AFJSONResponseSerializer serializer];
    session.responseSerializer = [AFHTTPResponseSerializer serializer];
    session.requestSerializer.timeoutInterval = 30;
    if (isJson){
        session.requestSerializer = [AFJSONRequestSerializer serializer];
    }
    
    session.requestSerializer.HTTPMethodsEncodingParametersInURI = [NSSet setWithObjects:@"GET", @"HEAD", nil];
    //    NSString *authToken = [fUserDefaults objectForKey:LOGIN_TOKEN];
    //    NSString *access_token = [fUserDefaults objectForKey:ACCESS_TOKEN];
    //    NSString *client_version = [fUserDefaults objectForKey:CLINET_VERSION];
    //    [session.requestSerializer setValue:client_version forHTTPHeaderField:CLINET_VERSION];
    //    [session.requestSerializer setValue:OPERATION_SYSTEM_VALUE forHTTPHeaderField:OPERATION_SYSTEM];
    //    [session.requestSerializer setValue:CLIENT_KEY_VALUE forHTTPHeaderField:CLIENT_KEY];
    //    if (authToken.length > 0) {
    //        NSString *token = [NSString stringWithFormat:@"Bearer %@",authToken];
    //        [session.requestSerializer setValue:token forHTTPHeaderField:@"Authorization"];
    //    }
    //
    //    if (access_token.length > 0) {
    //        [session.requestSerializer setValue:access_token forHTTPHeaderField:@"access_token"];
    //    }
    
    
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    NSString *encodeURL = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"`#%^{}\"[]|\\<> "].invertedSet];
    @weakify(self)
    switch (methodName) {
        case Get:{
            [session GET:encodeURL
              parameters:params headers:nil
                progress:^(NSProgress * _Nonnull downloadProgress) {
            }
                 success:^(NSURLSessionDataTask * _Nonnull task, NSData*  _Nullable responseObject) {
                //                     @strongify(self)
                
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                if(responseObject.length == 0){
                    return ;
                }
                id data = [responseObject objectFromJSONData];
                if (!data && responseObject) {
                    data = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
                    
                    NSDictionary *dict = [FSWHelperTool dictionaryWithJsonString:data];
                    XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n response:%@",session.requestSerializer.HTTPRequestHeaders,kNetworkMethodName[methodName],url,params,dict);
                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                        // time-consuming task
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [SVProgressHUD dismiss];
                        });
                    });
                    success(dict);
                    return;
                }
                if (!data) {
                    [FSWToast showWithText:@"序列化错误"];
                    return;
                }
                XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n response:%@",session.requestSerializer.HTTPRequestHeaders,kNetworkMethodName[methodName],url,params,data);
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    // time-consuming task
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [SVProgressHUD dismiss];
                    });
                });
                success(data);
            }
                 failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                @strongify(self);
                
                [self responsesError:error andDataTask:task andUrl:url andParames:params andHTTPRequestHeaders:session.requestSerializer.HTTPRequestHeaders andMethond:kNetworkMethodName[methodName]];
                
                NSHTTPURLResponse * responses = (NSHTTPURLResponse *)task.response;
                NSString * errorDesc = [NSString stringWithFormat:@"%zd",responses.statusCode];
                failure(errorDesc);
                
                
            }];
            break;
        }
        case Post:{
            [session POST:encodeURL
               parameters:params headers:nil
                 progress:^(NSProgress * _Nonnull uploadProgress) {
            }
                  success:^(NSURLSessionDataTask * _Nonnull task, NSData*  _Nullable responseObject) {
                //                      @strongify(self)
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                id data = [responseObject objectFromJSONData];
                if (!data && responseObject) {
                    data = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
                    success(data);
                    NSDictionary *dict = [FSWHelperTool dictionaryWithJsonString:data];
                    XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n response:%@",session.requestSerializer.HTTPRequestHeaders,kNetworkMethodName[methodName],url,params,dict);
                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                        // time-consuming task
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [SVProgressHUD dismiss];
                        });
                    });
                    return;
                }
                if (!data) {
                    [FSWToast showWithText:@"序列化错误"];
                    return;
                }
                XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n response:%@",session.requestSerializer.HTTPRequestHeaders,kNetworkMethodName[methodName],url,params,data);
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    // time-consuming task
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [SVProgressHUD dismiss];
                    });
                });
                success(data);
            }
                  failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                @strongify(self);
                
                [self responsesError:error andDataTask:task andUrl:url andParames:params andHTTPRequestHeaders:session.requestSerializer.HTTPRequestHeaders andMethond:kNetworkMethodName[methodName]];
                
                NSHTTPURLResponse * responses = (NSHTTPURLResponse *)task.response;
                NSString * errorDesc = [NSString stringWithFormat:@"%zd",responses.statusCode];
                failure(errorDesc);
                
            }];
            break;
        }
        case Patch:{
            [session PATCH:encodeURL parameters:params headers:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                //                @strongify(self)
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    // time-consuming task
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [SVProgressHUD dismiss];
                    });
                });
                success(responseObject);
                XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n response:%@",session.requestSerializer.HTTPRequestHeaders,kNetworkMethodName[methodName],url,params,responseObject);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                @strongify(self);
                
                [self responsesError:error andDataTask:task andUrl:url andParames:params andHTTPRequestHeaders:session.requestSerializer.HTTPRequestHeaders andMethond:kNetworkMethodName[methodName]];
                
                NSHTTPURLResponse * responses = (NSHTTPURLResponse *)task.response;
                NSString * errorDesc = [NSString stringWithFormat:@"%zd",responses.statusCode];
                failure(errorDesc);
                
            }];
            
            break;
        }
        case Put:{
            [session PUT:encodeURL
              parameters:params headers:nil
                 success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    // time-consuming task
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [SVProgressHUD dismiss];
                    });
                });
                success(responseObject);
                XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n response:%@",session.requestSerializer.HTTPRequestHeaders,kNetworkMethodName[methodName],url,params,responseObject);
            }
                 failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                @strongify(self);
                
                [self responsesError:error andDataTask:task andUrl:url andParames:params andHTTPRequestHeaders:session.requestSerializer.HTTPRequestHeaders andMethond:kNetworkMethodName[methodName]];
                
                NSHTTPURLResponse * responses = (NSHTTPURLResponse *)task.response;
                NSString * errorDesc = [NSString stringWithFormat:@"%zd",responses.statusCode];
                failure(errorDesc);
                
            }];
            break;
        }
        case Delete:{
            [session DELETE:encodeURL parameters:params headers:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                //                @strongify(self)
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                
                
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    // time-consuming task
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [SVProgressHUD dismiss];
                    });
                });
                success(responseObject);
                XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n response:%@",session.requestSerializer.HTTPRequestHeaders,kNetworkMethodName[methodName],url,params,responseObject);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                @strongify(self);
                
                [self responsesError:error andDataTask:task andUrl:url andParames:params andHTTPRequestHeaders:session.requestSerializer.HTTPRequestHeaders andMethond:kNetworkMethodName[methodName]];
                
                NSHTTPURLResponse * responses = (NSHTTPURLResponse *)task.response;
                NSString * errorDesc = [NSString stringWithFormat:@"%zd",responses.statusCode];
                failure(errorDesc);
                
            }];
            break;
        }
        default:
            break;
    }
}

- (void)requestHttpUploadWithMethod:(NetworkMethod)methodName url:(NSString *)url parameters:(NSDictionary *)params isJson:(BOOL)isJson image:(NSArray *)image success:(void (^)(id))success failure:(void (^)(NSString *))failure{
    
    
    AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
    session.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html",@"text/json",@"text/javascript",@"text/plain",@"text/xml", nil];
    session.responseSerializer = [AFJSONResponseSerializer serializer];
    session.requestSerializer.timeoutInterval = 30;
    NSString *authToken = [fUserDefaults objectForKey:LOGIN_TOKEN];
    NSString *access_token = [fUserDefaults objectForKey:ACCESS_TOKEN];
    NSString *client_version = [fUserDefaults objectForKey:CLINET_VERSION];
    [session.requestSerializer setValue:client_version forHTTPHeaderField:CLINET_VERSION];
    [session.requestSerializer setValue:OPERATION_SYSTEM_VALUE forHTTPHeaderField:OPERATION_SYSTEM];
    [session.requestSerializer setValue:CLIENT_KEY_VALUE forHTTPHeaderField:CLIENT_KEY];
    
    
    if (authToken.length > 0) {
        NSString *token = [NSString stringWithFormat:@"Bearer %@",authToken];
        [session.requestSerializer setValue:token forHTTPHeaderField:@"Authorization"];
    }
    
    if (access_token.length > 0) {
        [session.requestSerializer setValue:access_token forHTTPHeaderField:@"access_token"];
    }
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    NSString *encodeURL = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"`#%^{}\"[]|\\<> "].invertedSet];
    @weakify(self)
    switch (methodName) {
        case Post:{
            [session POST:encodeURL parameters:params headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
                for (NSData *data in image) {
                    
                    
                    // 在网络开发中，上传文件时，是文件不允许被覆盖，文件重名
                    // 要解决此问题，
                    // 可以在上传时使用当前的系统事件作为文件名
                    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
                    // 设置时间格式
                    formatter.dateFormat = @"YYYYMMddHHmmss";
                    NSString *str = [formatter stringFromDate:[NSDate date]];
                    NSString *fileName = [NSString stringWithFormat:@"%@.png", str];
                    
                    //上传
                    /*
                     此方法参数
                     1. 要上传的[二进制数据]
                     2. 对应网站上[upload.php中]处理文件的[字段"file"]
                     3. 要保存在服务器上的[文件名]
                     4. 上传文件的[mimeType]
                     */
                    [formData appendPartWithFileData:data name:@"image" fileName:fileName mimeType:@"image/png"];
                }
            }progress:^(NSProgress * _Nonnull uploadProgress) {
                //上传进度
                // @property int64_t totalUnitCount;     需要下载文件的总大小
                // @property int64_t completedUnitCount; 当前已经下载的大小
                //
                // 给Progress添加监听 KVO
                //                NSLog(@"%f",1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
                // 回到主队列刷新UI,用户自定义的进度条
                //                dispatch_async(dispatch_get_main_queue(), ^{
                //                    self.progressView.progress = 1.0 *
                //                    uploadProgress.completedUnitCount / uploadProgress.totalUnitCount;
                //                });
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    // time-consuming task
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [SVProgressHUD dismiss];
                    });
                });
                success(responseObject);
                XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n response:%@",session.requestSerializer.HTTPRequestHeaders,kNetworkMethodName[methodName],url,params,responseObject);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                @strongify(self);
                
                [self responsesError:error andDataTask:task andUrl:url andParames:params andHTTPRequestHeaders:session.requestSerializer.HTTPRequestHeaders andMethond:kNetworkMethodName[methodName]];
                
                NSHTTPURLResponse * responses = (NSHTTPURLResponse *)task.response;
                NSString * errorDesc = [NSString stringWithFormat:@"%zd",responses.statusCode];
                failure(errorDesc);
                
            }];
            break;
        }
            
        default:
            break;
    }
}


- (void)requestHttpUploadsWithMethod:(NetworkMethod)methodName url:(NSString *)url parameters:(NSDictionary *)params isJson:(BOOL)isJson image:(NSMutableDictionary *)image success:(void (^)(id))success failure:(void (^)(NSString *))failure{
    //    NSMutableArray *images = [NSMutableArray array];
    
    
    AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
    session.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html",@"text/json",@"text/javascript",@"text/plain",@"text/xml", nil];
    session.responseSerializer = [AFJSONResponseSerializer serializer];
    
    //   session.requestSerializer = [AFJSONRequestSerializer serializer];
    session.requestSerializer.timeoutInterval = 30;
    NSString *authToken = [fUserDefaults objectForKey:LOGIN_TOKEN];
    NSString *access_token = [fUserDefaults objectForKey:ACCESS_TOKEN];
    NSString *client_version = [fUserDefaults objectForKey:CLINET_VERSION];
    [session.requestSerializer setValue:client_version forHTTPHeaderField:CLINET_VERSION];
    [session.requestSerializer setValue:OPERATION_SYSTEM_VALUE forHTTPHeaderField:OPERATION_SYSTEM];
    [session.requestSerializer setValue:CLIENT_KEY_VALUE forHTTPHeaderField:CLIENT_KEY];
    
    
    if (authToken.length > 0) {
        NSString *token = [NSString stringWithFormat:@"Bearer %@",authToken];
        [session.requestSerializer setValue:token forHTTPHeaderField:@"Authorization"];
    }
    
    if (access_token.length > 0) {
        [session.requestSerializer setValue:access_token forHTTPHeaderField:@"access_token"];
    }
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    NSString *encodeURL = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"`#%^{}\"[]|\\<> "].invertedSet];
    @weakify(self)
    switch (methodName) {
        case Post:{
            [session POST:encodeURL parameters:params headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
                
                [image enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
                    UIImage *originImage =(UIImage *)obj;
                    NSString *keyStr = (NSString *)key;
                    NSData *imageData = UIImageJPEGRepresentation(originImage,0.1f);
                    NSString *fileName = [NSString stringWithFormat:@"%@.png", key];
                    [formData appendPartWithFileData:imageData name:keyStr fileName:fileName mimeType:@"image/png"];
                }];
            }progress:^(NSProgress * _Nonnull uploadProgress) {
                
            } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    // time-consuming task
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [SVProgressHUD dismiss];
                    });
                });
                success(responseObject);
                XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n response:%@",session.requestSerializer.HTTPRequestHeaders,kNetworkMethodName[methodName],url,params,responseObject);
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                @strongify(self);
                
                [self responsesError:error andDataTask:task andUrl:url andParames:params andHTTPRequestHeaders:session.requestSerializer.HTTPRequestHeaders andMethond:kNetworkMethodName[methodName]];
                
                NSHTTPURLResponse * responses = (NSHTTPURLResponse *)task.response;
                NSString * errorDesc = [NSString stringWithFormat:@"%zd",responses.statusCode];
                failure(errorDesc);
                
            }];
            break;
        }
            
        default:
            break;
    }
}

-(void)responsesError:(NSError *)error andDataTask:(NSURLSessionDataTask *)task andUrl:(NSString *)url andParames:(NSDictionary *)params andHTTPRequestHeaders:(NSDictionary *)headers andMethond:(NSString *)methond{
    [SVProgressHUD dismiss];
    NSHTTPURLResponse * responses = (NSHTTPURLResponse *)task.response;
    switch (responses.statusCode) {
        case 401:{
            [fUserDefaults setObject:nil forKey:ACCESS_TOKEN];
            [self goTologinViewController];
            XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n statusCode: %ld \n errorCode:%ld",headers,methond,url,params,(long)responses.statusCode,(long)error.code);
            break;
        } 
        default:{
            NSData *errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
            if (errorData) {
                NSDictionary *serializedData = [NSJSONSerialization JSONObjectWithData: errorData options:kNilOptions error:nil];
                if ([serializedData[@"success"] isEqualToString:@"false"]) {
                    if (![url isEqualToString:[NSString stringWithFormat:@"%@v1/shippers/version",BaseURL]]) {
                        [FSWToast showWithText:serializedData[@"message"]];
                    }
                    
                }
                XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n task:%@ \n statusCode: %ld \n errorCode:%ld",headers,methond,url,params,serializedData,(long)responses.statusCode,(long)error.code);
            }else{
                XCLog(@"%@\n methond:%@\n url:%@\n params:%@ \n statusCode: %ld \n errorCode:%ld",headers,methond,url,params,(long)responses.statusCode,(long)error.code);
            }
            
            break;
        }
    }
}

/**
 异地登录或登录过期
 */
- (void)goTologinViewController
{
    
}
- (UIViewController *)instantiateViewControllerWithStoryboardName:(NSString *)storyboardName identifier:(NSString *)identifier
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:[NSBundle mainBundle]];
    UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:identifier];
    return (UIViewController *)viewController;
}

 
@end
